package cn.wsalix.admin.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.anlaser.admin.BaseUser;
import cn.anlaser.service.impl.RelatedServiceImpl;
import cn.anlaser.status.FlagEnum;
import cn.anlaser.utils.SearchFilter;
import cn.anlaser.utils.SearchFilter.Operator;
import cn.wsalix.admin.entity.RoleMenu;
import cn.wsalix.admin.entity.SysMenu;
import cn.wsalix.admin.entity.SysRole;
import cn.wsalix.admin.form.MenuForm;
import cn.wsalix.admin.form.RoleMenuForm;
import cn.wsalix.admin.repository.RoleMenuRepository;
import cn.wsalix.admin.service.MenuService;
import cn.wsalix.admin.service.RoleMenuService;
import cn.wsalix.admin.service.UserRoleService;
import cn.wsalix.init.RoleInit;
import cn.wsalix.observable.service.MenuChangeService;

@Service("roleMenuService")
public class RoleMenuServiceImpl
		extends
		RelatedServiceImpl<RoleMenuForm, RoleMenuRepository, RoleMenu, SysRole, SysMenu>
		implements RoleMenuService {
	@Autowired
	private MenuService menuService;
	@Autowired
	private UserRoleService userRoleService;

	@Autowired
	private RoleInit roleInit;

	@Autowired
	private RoleMenuRepository roleMenuRepository;

	@Override
	public SysRole findPreFix(Long preFixId) {
		return userRoleService.findPostFix(preFixId);
	}

	@Override
	public SysMenu findPostFix(Long postFixId) {
		return menuService.findById(postFixId);
	}

	@Transactional
	@Override
	public void removeRelated(RoleMenuForm form) {
		if (form.getId() != null) {
			roleMenuRepository.delete(form.getId());
		} else {
			List<RoleMenu> roleMenus = findByForm(form);
			roleMenuRepository.delete(roleMenus);
		}

	}

	// @Cacheable(value = "myMenuCache",key = "#userId")
	@Transactional
	@Override
	public RoleMenu setRelated(RoleMenuForm form) {
		userRoleService.upUserRole(form.getRoleId());
		return super.setRelated(form);
	}

	@Override
	public List<RoleMenu> findRelateds(RoleMenuForm form) {
		if (form.getPreFixId() != null && form.getPreFixId() != 0) {
			return roleMenuRepository.findByRoleId(form.getPreFixId());
		}
		if (form.getPostFixId() != null && form.getPostFixId() != 0) {
			return roleMenuRepository.findByMenuId(form.getPostFixId());
		}
		return null;
	}

	@Override
	public List<SysRole> findUnPreFix(Long menuId) {
		return userRoleService.findUnRolesByMenuId(menuId);
	}

	@Override
	public List<SysMenu> findUnPostFix(Long roleId) {
		return menuService.findUnMenusByRoleId(roleId);
	}

	@Override
	public RoleMenuRepository getRepository() {
		return roleMenuRepository;
	}

	@Override
	public Map<String, SearchFilter> buildByForm(RoleMenuForm form) {
		Map<String, Object> searchParams = new HashMap<String, Object>();
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		if (form.getRoleId() != null && form.getRoleId() != 0) {
			filters.put("preFix.id", new SearchFilter("preFix.id", Operator.EQ,
					form.getRoleId()));
		}
		if (form.getMenuId() != null && form.getMenuId() != 0) {
			filters.put("postFix.id", new SearchFilter("postFix.id",
					Operator.EQ, form.getMenuId()));
		}
		return filters;
	}

	@Override
	public String module() {
		return "/admin/role_menu";
	}

	@Override
	public Class<RoleMenu> getEntityClazz() {
		return RoleMenu.class;
	}

	@Transactional
	@Override
	public void update(Observable o, Object arg) {
		if (o instanceof MenuChangeService) {
			MenuChangeService menuChangeService = (MenuChangeService) o;
			if (arg instanceof MenuForm) {
				MenuForm menuForm = (MenuForm) arg;
				SysMenu menu = null;
				switch (menuForm.getOperate()) {
				case add:
					menu = menuChangeService.getMenu();
					insertAdminMenu(menu);
					break;
				case del:
					menu = menuChangeService.getMenu();
					removeAdminMenu(menu);
					break;
				case edit:
					break;
				default:
					break;
				}
			}
		}
	}

	@Transactional
	private void removeAdminMenu(SysMenu menu) {
		SysRole role = roleInit.getAdmin();
		RoleMenuForm roleMenuForm = new RoleMenuForm();
		roleMenuForm.setMenuId(menu.getId());
		roleMenuForm.setRoleId(role.getId());
		removeRelated(roleMenuForm);
	}

	@Transactional
	private void insertAdminMenu(SysMenu menu) {
		SysRole role = roleInit.getAdmin();
		RoleMenu obj = new RoleMenu();
		obj.setPostFix(menu);
		obj.setPreFix(role);
		BaseUser user = userUtils.getUser();
		obj.setCreatedDate(new Date());
		if (user != null) {
			obj.setCreatedBy(user.getId());
		}
		obj.setFlag(FlagEnum.valid);
		add(obj);
	}
}
